<?php
namespace libraries;

use enums\HttpServerEnums;
use enums\ServiceEnums;
/*
 * 用redis实现跨服务器session
 * 注意需要安装phpredis模块
 *
 * 日期:2012-07-23 22:55:00
 * 
 * bruce modified
 */
class RedisSession implements \Phalcon\DI\InjectionAwareInterface//, \Phalcon\Session\AdapterInterface
{
    private $_lifetime = 86400;
 // 过期时间
    private $_sid = null;
 // session id
 //   private $session_folder;
 // session目录 
    private $_cookie_name = HttpServerEnums::SESSION_KEY;
 // cookie的名字
    private $_redis = null;
 // redis连接
    private $_cache = null;
   
    private $_sessionData = array();
   
    private $_di = null;
   
    private $_options = null;
    
    private $_cookies = null;
    
    private $_fetchMode = HttpServerEnums::SESSION_FETCH_MODE_SINGLE;
    
 // 缓存session
 //   private $expireAt;
 // 过期时间
 //   private $session_prefix;

    
    /*
     * 初始化
     * 参数
     * $redis:php_redis的类实例
     * $cookie_name:cookie的名字
     * $session_id_prefix:sesion id的前缀
     */
    public function __construct( $di, $options = null )
    {
    	$this->_di = $di;
    	
    	if( isset( $di->redisSession ))
    	{
       		$this->_redis = $di->redisSession;
    	}
    	
    	if( isset( $options ))
    	{
    		$this->_lifetime = isset( $options[ 'lifetime' ] ) ? $options[ 'lifetime' ] : $this->_lifetime;

    		$this->_fetchMode = isset( $options[ 'fetchMode' ] ) ? $options[ 'fetchMode' ] : HttpServerEnums::SESSION_FETCH_MODE_SINGLE;
    	}
    	
    	
    	$this->_cookies = $di->get( ServiceEnums::SERVICE_COOKIES );
    	
    }

    
    /*
     * 设置多个session的值
     * 参数
     * $array:值
     */
    public function setMulti( $array )
    {
    	if( !is_array( $array ) || 0 == count( $array ) )
    	{
    		return false;	
    	}
    	
    	foreach( $array as $k => $v )
    	{
    		$arr[ $k ] = serialize( $v );	
    	}
    	
        if( $this->_redis->hMSet( $this->_sid, $arr ))
        {
        	$this->_sessionData = array_merge( $this->_sessionData, $arr );
        	return true;
        }
        
        return false;
    }
    
    /**
     * 设置session id 一般用不到
     * @param unknown $id
     */
    public function setId( $id )
    {
        $this->_sid = $id;
        
        $cookie = $this->_cookies->get( HttpServerEnums::SESSION_KEY );
        
        if( !$cookie || $cookie && $cookie->getValue() != $id )
        {
        	$this->_cookies->set( HttpServerEnums::SESSION_KEY, $id );	
        }
        
        $this->_redis->expire( HttpServerEnums::SESSION_KEY, $this->_lifetime );
    }
    
    /*
     * 获取sessionid
     */
    public function getId()
    {
        return $this->_sid;
    }

//     private function checkCookie()
//     {
//     	if( empty($_COOKIE[ HttpServerEnums::SESSION_KEY ]) )
//     	{//libphp php-fpm .etc
    		
//     		$strSessionID = CommUtils::getUUIDNoDash();
// 	    	$this->setId( $strSessionID );
// 	    	$this->_cookies->set( HttpServerEnums::SESSION_KEY, $strSessionID );
//     	}
//     	else
//     	{    	
//     		$cookie = $this->_cookies->get( HttpServerEnums::SESSION_KEY );
    		
//     		if( $cookie->isUsingEncryption() )
//     		{//phalcon中的bug 导致getValue()在加密状态时取出的数据是错误的
//     			$crypt = $this->_di->get( 'crypt' );
//     			$strID = $crypt->decryptBase64( $_COOKIE[ HttpServerEnums::SESSION_KEY ] );
//     		}
//     		else 
//     		{
//     			$strID = $cookie->getValue();
//     		}

//     		$this->setId( $strID );
//     	}
    	 
//     }
    
    /*
     * 设置session的值
     * 参数
     * $key:session的key
     * $value:值
     */
    public function set( $key, $value )
    {
        if( is_null( $key ) || '' == $key || !is_string( $key ))
            return null;
        
        $strSerial = serialize( $value );
        if( false !== $this->_redis->hSet( $this->_sid, $key, $strSerial ))
        {
        	$this->_sessionData[ $key ] = $strSerial;
        	return true;
        }
        
        return false;
    }
    
    /*
     * 是否存在$key
     * $key:session的key
     */
    public function has($key)
    {
    	if( is_null( $key ) || '' == $key || !is_string( $key ))
    		return false;
    	
    	if( isset( $this->_sessionData[ $key ] ))
    	{
    		return true;	
    	}
    	
        if( false !== $this->_redis->hGet( $this->_sid, $key ) )
            return true;
        else
            return false;
    }

    /*
     * 设置session的值为对象
     * 参数
     * $key:session的key
     * $object:对象
     */
//     public function setObject($key, $object)
//     {
//     	if( is_null( $key ) || '' == $key || !is_string( $key ))
//     		return false;
    	
//         if( false !== $this->_redis->hSet( $this->_sid, $key, serialize($object)) )
//         {
//         	return true;
//         }
        
//         return false;
//     }

    /*
     * 获取全部session的key和value
     * @return: array
     */
    private function getAll()
    {
//     	if( is_null( $this->_sessionData ))
//     	{
        $this->_sessionData = $this->_redis->hGetAll( $this->_sid );
//     	}
    	
        $_SESSION = $this->_sessionData;
        
        return $this->_sessionData;
    }

    /*
     * 获取一个session的key和value
     * @return: array
     */
    public function get( $key )
    {
        if( is_null( $key ) || '' == $key || !is_string( $key ))
            return null;
        
        if( isset( $this->_sessionData[ $key ] ))
        {
        	return unserialize( $this->_sessionData[ $key ] );
        }
        
        if( $this->_fetchMode == HttpServerEnums::SESSION_FETCH_MODE_SINGLE )
        {
        	if( ( $result = $this->_redis->hGet( $this->_sid, $key) ) !== false )
        	{
        		$this->_sessionData[ $key ] = $result;
        		return unserialize( $this->_sessionData[ $key ] );
        	}
        }
        else
        {
        	$this->getAll();
        	
        	if( isset( $this->_sessionData[ $key ] ) )
        	{
        		return unserialize( $this->_sessionData[ $key ] );
        	}
        }

        return null;
    }

    /*
     * 获取session的值为对象
     * 参数
     * $key:session的key
     * $value:cookie的名字
     */
//     public function getObject( $key )
//     {
//     	if( is_null( $key ) || '' == $key || !is_string( $key ))
//             return null;
    	
//     	if( ( $result = $this->_redis->hGet( $this->_sid, $key) ) !== false )
//     	{
//     		return unserialize( $result );
//     	}
//     	return null;
//     }

    /*
     * 从缓存中获取一个session的key和value
     * @return: array
     */
//     public  function getFromCache( $key )
//     {
    	
//         if (! isset($this->cache)) 
//         {
//             $this->cache = $this->getAll();
//         }
        
//         return $this->cache[$key];
//     }

    /*
     * 删除一个session的key和value
     * @return: array
     */
    public function del( $key )
    {
    	if( is_null( $key ) || '' == $key || !is_string( $key ))
    	{
    		return false;
    	}
    	
        if( $this->_redis->hDel( $this->_sid, $key ) >= 0 )
        {
        	unset( $this->_sessionData[ $key ] );
        	return true;
        }
        
        return false;
    }

    /*
     * 删除所有session的key和value
     * @return: array
     */
//     public function delAll()
//     {
// //     	$this->checkCookie();
    	
//         return $this->_redis->del( $this->_sid );
//     }
    
    /**
     * 清除session中的所有数据 并设置session id 为 ''
     */
    public function destroy()
    {
        $iRet = $this->_redis->del( $this->_sid );
        
        if( $iRet > 0 )
        {
        	$this->_sid = '';
        	
        	$this->_sessionData = array();
        	
        	return true;
        }
        
        return false;
    }
    
    /**
     * {@inheritdoc}
     * @param string $maxLifetime
     */
    public function gc($maxLifetime)
    {
        return true;
    }
    
	/* (non-PHPdoc)
	 * @see \Phalcon\Di\InjectionAwareInterface::setDI()
	 */
	public function setDI(\Phalcon\DiInterface $dependencyInjector) 
	{
		$this->_di = $dependencyInjector;	
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Di\InjectionAwareInterface::getDI()
	 */
	public function getDI() 
	{
		return $this->_di;
	}

	/**
	 * @param $bDelOldSession 是否删除原session中的数据
	 * @see \Phalcon\Session\AdapterInterface::regenerateId()
	 */
	public function regenerateId( $bDelOldSession = true )
	{
		$strSessionID = CommUtils::getUUIDNoDash();

		if( $bDelOldSession )
		{
			$this->destroy();
			
			$this->setId( $strSessionID );
		}
		else
		{
			$arrSession = $this->toArray();
			
			$this->destroy();	
			$this->setId( $strSessionID );
			$this->setMulti( $arrSession );
		}
		
		return $strSessionID;
	}
	
	/* (non-PHPdoc)
	 * @see \Phalcon\Session\AdapterInterface::start()
	 */
	public function start() 
	{
		return true;
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Session\AdapterInterface::setOptions()
	 */
	public function setOptions(array $options) 
	{
		$this->_options = $options;
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Session\AdapterInterface::getOptions()
	 */
	public function getOptions() 
	{
		$this->_options;
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Session\AdapterInterface::remove()
	 */
	public function remove( $key ) 
	{
	 	return $this->del( $key );
// 		if( is_null( $key ) || '' == $key || !is_string( $key ))
// 			return false;
		
		
// 		return $this->_redis->hDel( $this->_sid, $key );
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Session\AdapterInterface::isStarted()
	 */
	public function isStarted() 
	{
		return true;
	}

	/* 
	 * setname 在session后设置已经不起作用
	 */
	public function setName($name) 
	{
		return true;
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Session\AdapterInterface::getName()
	 */
	public function getName() 
	{
		return ini_get( 'session.name' );
	}

	public function toArray()
	{
		$this->_sessionData = $this->getAll();
		
		foreach( $this->_sessionData as $k => $v )
		{
			$arr[ $k ] = unserialize( $v );
		}
		
		return $arr;
	}
	
}
?>